#include "../include/kc.h"
#include "../include/buffer.h"

#define STDOUT 1
#define STDIN 0
/***************************************************************
*StrCmp
*
* Compara 2 Strings.
****************************************************************/


/*
void int_80(){
}
*/
void daError(){
	int a=0;
	a = 20/0;
}

void daExpOut(){
	_overflow();
}

void daOpcode(){
	_invalid_opcode();
}

void daSegNotPresent(){
/*	int i = 10;
	DESCR_SEG aux;
	unsigned long base = atol("111");
	unsigned long limite = atol("34") & 0x0ffff;
	unsigned char access = ((atoi("2") << 1 | 1 ) << 4) | (atoi("1") << 1 | 0);
	unsigned char atrib = ((atoi("34") >> 16) & 15) |( 8 << 4 );
	gdt_set_gate(&gdt[i], base, limite, access, atrib);
	aux.access=gdt[i].access;
	aux.attribs=gdt[i].attribs;
	aux.base_h=gdt[i].base_h;
	aux.base_l=gdt[i].base_l;
	aux.base_m=gdt[i].base_m;
	aux.limit=gdt[i].limit;
	_seg_not_present();*/
}


void excp_0() {
    print("Exception: zero divide\n");
}

void excp_04() {
    print("Exception: Overflow\n");
}

void excp_06() {
    print("Exception: Invalid Opcode\n");
}

void excp_11() {
    print("Exception: Segment Not Present\n");
}

char getchar(void)
{
	return _Read(STDIN);
}


void putchar(char charac)
{
	_Write(STDOUT, charac);
}

void print(char text[]){
int i = 0;
	while(text[i] != '\0')
	{
		if (text[i] == '\n')
			newLineCursor();
		else
			putchar(text[i]);

		i++;
	}
}


void fmtprint(char * text, int cant){
int formatdef , i;
  formatdef =	getDefaultFormat();
	int max;
	max =  cant;
	for(i=0; i < max; i++)
	{
		setDefaultFormat(text[i+1]);

		putchar(text[i]);
		InsertKey(text[i]);
		i++;
	}
	setDefaultFormat(formatdef);
}


int
strCmp(char *s1, char *s2)
{
	while (*s1 == *s2)
	{
		s1++;
		s2++;
		if (*s1 == '\0' && '\0' == *s2)
			return(1);
	}
	return(0);
}

int
atoi(const char* string){
	int rta = 0;
	int sign = 1;
	int cont = 0;
	while (*string == ' ')
		 string++;
	if(*string == '-')
	{
	  string++;
	  sign= -1;
	}
	while((*string)<='9' && (*string)>='0' && cont < 5)
	{
	  rta*=10;
	  rta+=(*string)-'0';
	  string++;
	  cont++;
	}
	return rta*sign;
}

long
atol(const char* string){
	long rta = 0;

	int cont = 0;
	while (*string == ' ')
		 string++;

	while((*string)<='9' && (*string)>='0')
	{
	  rta*=10;
	  rta+=(*string)-'0';
	  string++;
	  cont++;
	}
	return rta;
}



/***************************************************************
*k_clear_screen
*
* Borra la pantalla en modo texto color.
****************************************************************/
/*
void k_clear_screen()
{
	char *vidmem = (char *) 0xb8000;
	unsigned int i=0;
	while(i < (80*25*2))
	{
		vidmem[i]='7';
		i++;
		vidmem[i]=WHITE_TXT;
		i++;
	};
}*/
/***************************************************************
*setup_IDT_entry
* Inicializa un descriptor de la IDT
*
*Recibe: Puntero a elemento de la IDT
*	 Selector a cargar en el descriptor de interrupcion
*	 Puntero a rutina de atencion de interrupcion
*	 Derechos de acceso del segmento
*	 Cero
****************************************************************/

void setup_IDT_entry (DESCR_INT *item, byte selector, dword offset, byte access, byte cero) {
  item->selector = selector;
  item->offset_l = offset & 0xFFFF;
  item->offset_h = offset >> 16;
  item->access = access;
  item->cero = cero;
}

/******************************************************************************/

/* A continuacion se incluyen las funciones de entrada y salida destinadas al
 * usuario final. Estas son:
 *
 * printf(), cuya forma de uso es igual al de la biblioteca standar de c. El
 * codigo de printf() fue extraido de:
 *
 *						Multiboot Specification
 *						Free Software Foundation
 *						http://www.gnu.org/software/grub/manual/multiboot/
 *
 * getstring(), que devuelve un string con las teclas ingresadas al presionar
 * enter.
 *
 */

/******************************************************************************/

/*
 * -----------------
 * Funciones para manipular strings. El codigo de itoa fue extraido de:
 *
 *				Multiboot Specification
 *				Free Software Foundation
 *				last updated June 24, 2006
 *				http://www.gnu.org/software/grub/manual/multiboot/
 */

void
itoa (char *buf, int base, int d)
{
	char *p = buf;
	char *p1, *p2;
	char tmp;
	unsigned long ud = d;
	int divisor = 10;
	int remainder;

	/* If %d is specified and D is minus, put '-' in the head. */

	if (base == 'd' && d < 0)
	{
		*p++ = '-';
		buf++;
		ud = -d;
	}
	else if (base == 'x')
	{
		divisor = 16;
	}

	/* Divide UD by DIVISOR until UD == 0. */

	do
	{
		remainder = ud % divisor;
		*p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;

	} while (ud /= divisor);

	/* Terminate BUF. */

	*p = 0;

	/* Reverse BUF. */

	p1 = buf;
	p2 = p - 1;

	while (p1 < p2)
	{
		tmp = *p1;
		*p1 = *p2;
		*p2 = tmp;
		p1++;
		p2--;
	}
}

void
ltoa (char *buf, int base, long d)
{
	char *p = buf;
	char *p1, *p2;
	char tmp;
	unsigned long ud = d;
	int divisor = 10;
	long remainder;

	/* If %d is specified and D is minus, put '-' in the head. */

	if (base == 'd' && d < 0)
	{
		*p++ = '-';
		buf++;
		ud = -d;
	}
	else if (base == 'x')
	{
		divisor = 16;
	}

	/* Divide UD by DIVISOR until UD == 0. */

	do
	{
		remainder = ud % divisor;
		*p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;

	} while (ud /= divisor);

	/* Terminate BUF. */

	*p = 0;

	/* Reverse BUF. */

	p1 = buf;
	p2 = p - 1;

	while (p1 < p2)
	{
		tmp = *p1;
		*p1 = *p2;
		*p2 = tmp;
		p1++;
		p2--;
	}
}


void
printf ( const char *format, ... )
{
	char **arg = (char **) &format;
	int c;
	char buf[20];

	_Cli ();

	arg++;

	while ((c = *format++) != 0)
	{
		if (c != '%')
		{
			putchar ( c );
		}
		else
		{
			char *p;
			c = *format++;

			switch (c)
			{
				case 'd':
				case 'u':
				case 'x':
					itoa (buf, c, *((int *) arg++));
					p = buf;
					goto string;
					break;
				case'l':
					ltoa ( buf, 'x', *((long *) arg++));
					p = buf;
					goto string;
					break;

				case 's':
					p = *arg++;
					if (! p)
						p = "(null)";

				string:
					while (*p)
						putchar (*p++);
					break;

				default:
					putchar (*((int *) arg++));
					break;
			}
		}
	}

	_Sti ();
}
